But there still remains a question: equality or inequality of what? - Aristotle, Politics
One of the uglier parts of Prolog is the way that it has many different ways to write equality or inequality, with subtly different shades of meaning. Here are some of them:
| Operator | Meaning |
|---|---|
= |
The two sides can and do unify (can be made the same) |
\= |
The two sides cannot be made to unify |
== |
The two sides are already the same |
\== |
The two sides are not already the same |
is |
The left side unifies with the value of the right-hand-side |
=:= |
The value of the left is equal to the value of the right |
< |
The value of the left is less than the value of the right |
=< |
The value of the left is less-than-or-equal-to the value of the right |
The = operator in Prolog attempts to unify two terms,
and fails if it cannot.
The \= operator succeeds when given two terms that
cannot be unified, but fails if they could unify (though Prolog does not
unify them in that case, since the failure forces backtracking).
Example
Assume each of the following is a separate query (so that all variables start out unset in each case, and each query is independent of the others):
X = a.Succeeds and defines
Xtoa.[X,a] = [b,Y].Succeeds and defines
XtobandYtoa.X = [Y].Succeeds and defines
Xto be the list[Y]but leavesYundetermined).X = [X].Perhaps surprisingly, succeeds and defines
Xto be the list[X]This is implemented by defining
Xto be a linked list of length 1 whose only data is a pointer to the list itself.It’s rather questionable whether this should be allowed, but detecting such pathological cases - known as an occurs check because it checks for circular definitions where the variable we are defining occurs in the proposed definition - would be extra work every unification. Since unification is such a fundamental operation in Prolog and executes so frequently, it was decided that doing the occur check would make Prolog too slow.
X \= Y.Fails, since we could have made both sides equal by defining
Xto beYor vice-versa.X = 3, Y = 2, X = Y.Fails, since by the time we get to
X = Y, we have already decided thatXmust be 3 andYmust be 2, and there’s no way to make 3 unify with 2.X = 3, Y = 2, X \= Y.Succeeds, since by the time we get to
X \= Y, we have decided thatXmust be 3 andYmust be 2, and it is correct to say that 3 cannot be unified with 2. ## Structural Equality
The operator == succeeds if the two terms are
already the same, and fails otherwise. Unlike the unification
operator =, the == operator never sets any
variables.
The operator \= succeeds if the two terms are
not the same, and fails if they are already the same.
Example
Assume each of the following is a separate query (so that all
variables start out unset in each case, and each query is independent of
the others): > > prolog > X == a. > >
> Fails, since X starts out unset and so is not yet the
same as a. > >
prolog > [X,a] == [b,Y]. > > > Fails, since
the list [X,a] (containing an unset variable
X) is not the same as the list [b,Y]
(containing an unset variable Y). > >
prolog > X == [X]. > > > Fails, since the
unset variable X is not already equal to a list. > >
prolog > X = [X], X == [X]. > > > Succeeds,
since by the time we check X == [X] we have already use
definition to make [X] the definition of X.
> > prolog > 1+2 == 1+2. > > >
Succeeds, since both sides are the same term. > >
prolog > 1+2 == 2+1. > > > Fails, since
1+2 is literally a different term than 2+1.
(Prolog does not evaluate terms like 1+2 unless we
use specific operators like is to force that to happen!)
> > prolog > X = 3, Y = 3, X==Y. > >
> Succeeds, since by the time we get to X==Y we have
defined both X and Y to be 3.
The most important operator for doing arithmetic in Prolog is the
is operator; this unifies the left-hand term with
the evaluated value of the right-hand term.
Comparisons like < and =< (Prolog’s
way of saying less-than-or-equal-to) evaluate both sides, and
then succeed or fail based on the result of the comparison.
Example
Assume each of the following is a separate query (so that all variables start out unset in each case, and each query is independent of the others):
:::
> X is 5+2.
> ```
>
> Succeeds, and sets `X = 7` .
>
> ```prolog
> X is Y*7.
> ```
>
> Fails, since `Y` is undefined and so we cannot evaluate `Y*7` to a value.
>
> ```prolog
> Y = 6, X is Y*7.
> ```
>
> Succeeds, and sets `Y = 6, X = 42`. The difference from the previous example is that by the time we need to calculate `Y*7`, we have already defined `Y` to be 7.
>
> ```prolog
> 1+2 is 2+1.
> ```
>
> Fails, since `is` only evaluates the right-hand-side, and the term `1+2` does not unify (cannot be made identical) to the value `3`.
>
> (The operator `=:=` evaluates both sides and checks for equality, but it's rarely needed.)
## Doing Calculations
Newcomers to Prolog may be tempted to write
```prolog
fac(0) :- 1.
fac(X) :- X * fac(X-1).but this is totally broken.
1 as a
right-hand-side.X by the result of a relation makes no
sense.We can express this recursive computation in Prolog, but need to define the relation between the input and the output:
fac(0, 1). % Input 0 is related to output 1
fac(N, X) :- Nminus1 is N-1,
fac(Nminus1, Nminus1Factorial),
X is N * Nminus1Factorial.We have to be careful to use is in this code to force
Prolog to do the arithmetic and give a name to the result; if we just
passed N-1 to the recursive call Prolog would start
building unevaluated terms like N-1, N-1-1,
N-1-1-1, … and these terms would never unify with
the number 0 in our base case.
Previous: 4.7 Lists in Prolog
Next: 4.9 Negation in Prolog